package com.wonderful.map.view

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import android.text.TextPaint
import android.util.AttributeSet
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.ImageView
import androidx.annotation.DrawableRes
import com.wonderful.map.R
import com.wonderful.map.bean.PointBean
import com.wonderful.map.utils.DensityUtil
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.roundToInt

/**
 * Desc: 点 Point view
 * @Author: wonderful
 * @Time: 2023/5/10 17:40
 */
class PointView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0,
    @DrawableRes pointRes: Int
) : ViewGroup(context, attrs, defStyleAttr, defStyleRes) {

    companion object {
        private const val VIEW_SIZE = 10f
        private const val TEXT_SIZE = 25f
        private const val TEXT_PADDING_BOTTOM = 10f // 文字离点的距离
    }

    private val mImageView = ImageView(context)

    // 点名称
    private val mTextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
    private var mTextSize = TEXT_SIZE
    private var mTextPaddingBottom = TEXT_PADDING_BOTTOM
    private var mTextWidth = 0f
    private var mPointName = ""
    private var isShowPointName = true // 是否显示点名称

    // 方向箭头
    private val mArrowPaint = Paint()
    private var mArrowBitmap: Bitmap
    private var mArrowWidth = 0f
    private var mArrowAngle = 0f    // 箭头角度
    private var mMatrixRotateAngle = 0f
    private var isShowArrow = true // 是否显示箭头


    // 点位置坐标
    private val mPointF = PointF(0f, 0f)
    private var mPointBean: PointBean? = null

    // 点中间偏移距离
    private var mPointOffsetX = 0f
    private var mPointOffsetY = 0f

    private var mPointId = ""

    init {
        // 初始化点图片
        val imageViewParams = LayoutParams(
            DensityUtil.dp2px(context, VIEW_SIZE),
            DensityUtil.dp2px(context, VIEW_SIZE)
        )
        viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
            override fun onPreDraw(): Boolean {
                viewTreeObserver.removeOnPreDrawListener(this)
                x = mPointF.x - mPointOffsetX
                y = mPointF.y - mPointOffsetY
                return true
            }
        })
        mImageView.setImageResource(pointRes)
        mImageView.layoutParams = imageViewParams
        addView(mImageView)

        // 初始化文字 paint
        mTextPaint.apply {
            color = Color.BLACK
            textSize = DensityUtil.px2sp(context, mTextSize).toFloat()
        }

        setWillNotDraw(false)

        // 初始化箭头
        mArrowBitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_arrow)
        mArrowWidth = mArrowBitmap.width.toFloat()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var width = mTextWidth.coerceAtLeast(VIEW_SIZE.dp().toFloat()).roundToInt()
        if (width < mArrowWidth * 2) {
            width = (mArrowWidth * 2).roundToInt()
        }
        val height = mImageView.measuredHeight + mTextSize.dp() + mTextPaddingBottom.dp()
        setMeasuredDimension(width, height)
        // 计算偏移距离
        mPointOffsetX = (width / 2).toFloat()
        mPointOffsetY = (height - VIEW_SIZE.dp() - mTextPaddingBottom.dp()).toFloat()
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        getChildAt(0).layout(
            measuredWidth / 2 - VIEW_SIZE.dp() / 2,
            measuredHeight - VIEW_SIZE.dp() - mTextPaddingBottom.dp(),
            measuredWidth / 2 + VIEW_SIZE.dp() / 2,
            measuredHeight - mTextPaddingBottom.dp()
        )
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (isShowPointName) {
            var startX = 0f
            if (mTextWidth < mArrowWidth * 2) {
                startX = mArrowWidth - mTextWidth / 2
            }
            canvas?.drawText(mPointName, startX, abs(mTextPaint.fontMetrics.top), mTextPaint)
        }
        if (isShowArrow) {
            canvas?.apply {
                save()
                rotate(mArrowAngle + mMatrixRotateAngle, mPointOffsetX, mPointOffsetY)
                drawBitmap(mArrowBitmap, mPointOffsetX, mImageView.top.toFloat(), mArrowPaint)
                restore()
            }
        }
    }

    private fun Float.dp(): Int {
        return DensityUtil.dp2px(context, this)
    }

    /**
     * 设置角度
     */
    fun setAngle(angle: Float) {
        mArrowAngle = angle
        if (isShowArrow) invalidate()
    }

    fun setMatrixRotateAngle(angle: Float) {
        mMatrixRotateAngle = angle
        if (isShowArrow) invalidate()
    }

    /**
     * 设置是否显示箭头
     */
    fun setShowArrow(isShow: Boolean) {
        if (isShowArrow == isShow) return
        isShowArrow = isShow
        postInvalidate()
    }

    /**
     * 设置是否显示名称
     */
    fun setShowPointName(isShow: Boolean) {
        if (isShowPointName == isShow) return
        isShowPointName = isShow
        invalidate()
    }

    /**
     * 设置 point 图片
     */
    fun setPointImage(@DrawableRes imgRes: Int) {
        mImageView.setImageResource(imgRes)
    }

    /**
     * 设置 point
     */
    fun setPoint(point: PointBean) {
        mPointBean = point
        mPointName = point.name
        mPointId = point.id
        mTextWidth = max(mTextPaint.measureText(mPointName), 0f) + 0.5f
    }

    /**
     * 设置点位置坐标
     *
     * @param pointF 转换后的 view 坐标
     */
    fun setPointF(pointF: PointF) {
        mPointF.set(pointF)
        x = pointF.x - mPointOffsetX
        y = pointF.y - mPointOffsetY
    }

    fun getPointId(): String = mPointId

    fun getPointName(): String = mPointName

    fun getPointBean(): PointBean? = mPointBean
}